﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Uniloader.Interface;
using Uniloader.Managers;
using System.IO;
using MonoTorrent.Client;
using MonoTorrent.Common;
using System.Net;
using System.ComponentModel;
using System.Windows.Threading;

namespace XamlTorrent.Managers.MonoTorrent.UI
{
    /// <summary>
    /// Interaction logic for CreateTorrentTask.xaml
    /// </summary>
    public partial class CreateTorrentTask : UserControl, ITransferTaskFactory 
    {
        public CreateTorrentTask(MonoTorrentManager manager)
        {
            torrentManager = manager;

            InitializeComponent();
        }

        MonoTorrentManager torrentManager;

        #region ITransferTaskFactory Members

        public TransferTask CreateTask()
        {
            Uri torrentFileUri = null;
            Uri.TryCreate(torrentUri.Text, UriKind.RelativeOrAbsolute, out torrentFileUri);
            
            FileSystemInfo saveTo = new FileInfo(saveLocation.Text);
            if ((saveTo.Attributes | FileAttributes.Directory) != 0)
                saveTo = new DirectoryInfo(saveLocation.Text);
            
            MonoTorrentTask task = new MonoTorrentTask(null, saveTo);

            torrentManager.AddTask(task);

            return task;
        }

        #endregion

        #region Properties
        public static readonly DependencyProperty LoadedTorrentProperty = DependencyProperty.Register("LoadedTorrent", typeof(Torrent), typeof(CreateTorrentTask));
        /// <summary>
        /// Currently loaded torrent file.
        /// </summary>
        protected Torrent LoadedTorrent
        {
            get { return (Torrent)this.GetValue(LoadedTorrentProperty); }
            set
            {
                this.SetValue(LoadedTorrentProperty, value);

                // Update the SelectedFilesCount, all initially selected.
                if (value != null)
                    this.SetValue(SelectedFilesCountProperty, value.Files.Length);
                else
                    this.SetValue(SelectedFilesCountProperty, 0);
            }
        }

        public static readonly DependencyProperty SelectedFilesCountProperty = DependencyProperty.Register("SelectedFilesCount", typeof(int), typeof(CreateTorrentTask));
        /// <summary>
        /// Number of files selected for download withing the torrent.
        /// </summary>
        protected int SelectedFilesCount
        {
            get { return (int)this.GetValue(SelectedFilesCountProperty); }
        } 
        #endregion

        #region Load torrent file data
        /// <summary>
        /// Attempts to load the torrent file from the path in torrentUri.Text.
        /// </summary>
        private void torrentUri_LostFocus(object sender, RoutedEventArgs e)
        {
            Uri torrentFileUri = null;
            if (Uri.TryCreate(torrentUri.Text, UriKind.Absolute, out torrentFileUri))
            {
                LoadedTorrent = null;

                try
                {
                    WebRequest webReq = WebRequest.Create(torrentFileUri);
                    webReq.BeginGetResponse(ReadTorrentCallback, webReq);
                }
                catch (WebException)
                {
                }
            }
        }

        /// <summary>
        /// Helper delegate to pass anonnymous methods to Dispatcher.Invoke.
        /// </summary>
        private delegate void SetLoadedTorrentDelegate(Torrent value);

        /// <summary>
        /// Reads the content of the torrent. To be used as a parameter to WebRequest.BeginGetResponse.
        /// </summary>
        public void ReadTorrentCallback(IAsyncResult ar)
        {
            WebRequest webReq = (WebRequest)ar.AsyncState;

            try
            {
                WebResponse webResp = webReq.EndGetResponse(ar);

                using (Stream torrentData = webResp.GetResponseStream())
                {
                    Torrent newTorrent = null;
                    Torrent.TryLoad(torrentData, out newTorrent);

                    SetLoadedTorrentDelegate setTorrent = delegate(Torrent value) { LoadedTorrent = value; };

                    // DependancyProperty must be updated by the UI thread.
                    Dispatcher.Invoke(DispatcherPriority.Normal, setTorrent, newTorrent);
                }
            }
            catch (WebException)
            {
            }
        } 
        #endregion

        /// <summary>
        /// Updates SelectedFilesCount property when a checkbox in the file list is checked/unchecked.
        /// </summary>
        /// <param name="sender">CheckBox whose status changed.</param>
        private void FileCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = (CheckBox)sender;

            if (checkBox.IsChecked ?? false)
                this.SetValue(SelectedFilesCountProperty, SelectedFilesCount + 1);
            else
                this.SetValue(SelectedFilesCountProperty, SelectedFilesCount - 1);
        }
    }
}
